<?
/*数据库访问类
*一个方法干一件事
*/

class Db{
	private $where=array(); //给where一个初始值，防止没有wehwe时报错
	private $field='*'; //查询字段
	private $order=''; //排序
	private $limit=0; //数据条数，0表示不限制
	private $pdo=null;

	// 构造函数
	public function __construct(){
		$this->pdo=new PDO('mysql:host=127.0.0.1;dbname=blog','root','123456789');
		$this->pdo->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION); //返回错误信息
	}
	// 指定表名称
	public function table($table){
		$this->table=$table;
		return $this; //当前对象(Db)
	}

	// 指定查询字段
	public function field($field){
		$this->field=$field;
		return $this;
	}

	// 指定排序条件
	public function order($order){
		$this->order=$order;
		return $this;
	}

	// 执行查询数量
	public function limit($limit){
		$this->limit=$limit;
		return $this;
	}

	// 指定where条件
	public function where($where){
		$this->where=$where;
		return $this;
	}

	// 查询一条数据记录
	public function item(){
		$sql=$this->_build_sql('select').' limit 1'; //调用sql
		$stmt=$this->pdo->prepare($sql);
		$stmt->execute();
		$res=$stmt->fetchAll(PDO::FETCH_ASSOC);
		return isset($res[0])?$res[0]:false; //三目运算符判断数据是否存在
	}

	// 查询多条数据
	public function lists(){
		$sql=$this->_build_sql('select'); //调用sql
		$stmt=$this->pdo->prepare($sql);
		$stmt->execute();
		return $stmt->fetchAll(PDO::FETCH_ASSOC);
	}

	// 查询数据总数
	public function count(){
		$sql=$this->_build_sql('count');
		$stmt=$this->pdo->prepare($sql);
		$stmt->execute();
		$total=$stmt->fetchColumn(0); //总数
		return $total;
	}

	// 分页查询
	public function pages($page,$pageSize=10,$path='/'){
		$count=$this->count();
		$this->limit=($page-1)*$pageSize.','.$pageSize;
		$data=$this->lists();
		$pages=$this->_subPages($page,$pageSize,$count,$path); //分页html
		return array('total'=>$count,'data'=>$data,'pages'=>$pages);
	}

	// 生成分页html(bootstrap风格);$cur_page:当前是第几页,$pageSize:每页条数,$total:数据总数,$path:页面路径
	private function _subPages($cur_page,$pageSize,$total,$path){
		// 每次最多展示多小页

		$symbol='?'; //符号
		$index=strpos($path,'?');// 判断$path中是否含有?
		if($index!==false&&$index>0){
			$symbol='&';
		}

		$html='';
		$page_count=ceil($total/$pageSize); //分页数（向上取整）

		// 生成首页、生成上一页
		if($cur_page>1){
			// 生成首页
			$html.="<li><a href='{$path}{$symbol}page=1'>首页</a></li>";
			//生成上一页
			$pre_page=$cur_page-1;
			$html.="<li><a href='{$path}{$symbol}page={$pre_page}'>上一页</a></li>";
		}
		// 生成数字页
		$end=($cur_page+5)>$page_count?$page_count:($cur_page+5); // 结束页
		$start=($end-9)<=0?1:($end-9); // 开始页

	/*	$num=6;  
		// $start=$cur_page>($cur_page-$num)?($cur_page-$num):$cur_page; //开始页
		// 开始页
		$start=$cur_page>($page_count-6)?($page_count-6):$cur_page;
		$start=$start-2;
		$start=$start<=0?1:$start;
		// 结束页
		$end=($cur_page+$num)>$page_count?$page_count:($cur_page+$num);
		$end=$end-2;
		// 
		if($cur_page+2>$end&&$page_count>6){
			$start=$start+2;
			$end=$end+2;
		} */

		for($i=$start;$i<=$end;$i++){
			$html.=$i==$cur_page?"<li class='active'><a>{$i}</a></li>":"<li><a href='{$path}{$symbol}page={$i}'>{$i}</a></li>";
		}
		// 生成下一页、生成尾页
		if($cur_page<$page_count){
			$after_page=$cur_page+1;
			$html.="<li><a href='{$path}{$symbol}page={$after_page}'>下一页</a></li>";
			// 生成尾页
			$html.="<li><a href='{$path}{$symbol}page={$page_count}'>尾页</a></li>";
		}

		// 连接html
		$html='<nav aria-label="Page navigation"><ul class="pagination">'.$html.'</ul></nav>';
		return $html;
	}

	// 添加数据
	public function insert($data){
		$sql=$this->_build_sql('insert',$data);
		$stmt=$this->pdo->prepare($sql);
		$stmt->execute();
		return $this->pdo->lastInsertId();
	}

	// 删除数据
	public function delete(){
		$sql=$this->_build_sql('delete');
		$stmt=$this->pdo->prepare($sql);
		$stmt->execute();
		return $stmt->rowCount(); //返回受影响的行数
	}

	// 更新数据
	public function update($data){
		$sql=$this->_build_sql('update',$data);
		$stmt=$this->pdo->prepare($sql);
		$stmt->execute();
		return $stmt->rowCount();
	}

	// 构造sql语句（私有函数，本类调用）
	private function _build_sql($type,$data=null){
		// 查询
		if($type=='select'){
			$where=$this->_build_where(); //调用where条件
			$sql="select {$this->field} from {$this->table} {$where}";
			if($this->order){
				$sql.=" order by {$this->order}"; //排列
			}
			if($this->limit){ //判断limit有值
				$sql.=" limit {$this->limit}"; //数据数量
			}
		}

		// count(数据总数)
		if($type=='count'){
			$where=$this->_build_where();
			$field_list=explode(',',$this->field); //字符串转成数组
			$field=count($field_list)>1?'*':$this->field; //判断数组个数是否大于1
			$sql="select count({$field}) from {$this->table} {$where}";
		}

		// 添加
		if($type=='insert'){
			$sql="insert into {$this->table}";
			$fields=$values=[];
			foreach ($data as $key => $val) {
				$fields[]="`".$key."`";
				$values[]=is_string($val)?"'".$val."'":$val;
			}
			$sql.="(".implode(',',$fields).")values(".implode(',',$values).")";
		}

		// 删除
		if($type=='delete'){
			$where=$this->_build_where();
			$sql="delete from {$this->table} {$where}";
		}

		// 更新
		if($type=='update'){
			$where=$this->_build_where(); //生成where条件
			// 生成set
			$str='';
			foreach ($data as $key => $val) {
				$val=is_string($val)?"'".$val."'":$val;
				$str.="{$key}={$val},";
			}
			$str=rtrim($str,',');
			$str=$str?" set {$str}":'';
			$sql="update {$this->table} {$str} {$where}";
		}

		return $sql;
	}

	// 组装where条件字符串
	private function _build_where(){
		$where='';
		if(is_array($this->where)){
			// 数组
			foreach ($this->where as $key => $value) {
				$value=is_string($value)?"'".$value."'":$value; //字符串加引号
				$where.="`{$key}`={$value} and"; //避免与关键字冲突，给字段加``
			}
		}else{
			// 字符串
			$where=$this->where;
		}
		$where=rtrim($where,'and '); //去掉右侧的and
		$where=$where==''?'':"where {$where}"; //判断wehere是否存在
		return $where;
	}
}
?>